import { JavascriptGenerator, javascriptGenerator } from "blockly/javascript";
import { Tanslate } from "./translate";
import * as Blockly from 'blockly/core';
import { WorkspaceSvg } from "blockly/core";
import { getValue } from "./com";

/**
  列表扩充
**/
export namespace Lists {
    const blocks = [
        {
            'key': 'lists_create_empty',
            'message0': '%{BKY_LISTS_CREATE_EMPTY_TITLE}',
            'output': 'Array',
            'style': 'list_blocks',
            'tooltip': '%{BKY_LISTS_CREATE_EMPTY_TOOLTIP}',
            'helpUrl': '%{BKY_LISTS_CREATE_EMPTY_HELPURL}',
        },
        {
            'key': 'lists_repeat',
            'message0': '%{BKY_LISTS_REPEAT_TITLE}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'ITEM',
                },
                {
                    'type': 'input_value',
                    'name': 'NUM',
                    'check': 'Number',
                },
            ],
            'output': 'Array',
            'style': 'list_blocks',
            'tooltip': '%{BKY_LISTS_REPEAT_TOOLTIP}',
            'helpUrl': '%{BKY_LISTS_REPEAT_HELPURL}',
        },
        {
            "key": "list_custom",
            "message0": "%{list_custom} \n %1 %2  %3 %4 %5 %6 %7",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value_0"
                },
                {
                    "type": "input_value",
                    "name": "value_1"
                },
                {
                    "type": "input_value",
                    "name": "value_2"
                },
                {
                    "type": "input_value",
                    "name": "value_3"
                },
                {
                    "type": "input_value",
                    "name": "value_4"
                },
                {
                    "type": "input_value",
                    "name": "value_5"
                },
                {
                    "type": "input_value",
                    "name": "value_6"
                }
            ],
            "output": "Array",
            "colour": 240
        },
        {
            "key": "list_merge",
            "message0": "%{list_merge} %1 %{list_separator} %2",
            "args0": [
                {
                    "type": "input_value",
                    "name": "list",
                    "check": "Array"
                },
                {
                    "type": "input_value",
                    "name": "separator",
                    "check": "String"
                }
            ],
            "output": "String",
            "inputsInline": true,
            "colour": 240
        },
        {
            "key": "get_list_length",
            "message0": "%{get} %1 %{size}",
            "args0": [
                {
                    "type": "input_value",
                    "name": "value",
                    "check": "Array"
                }
            ],
            "output": "Number",
            "colour": 240
        },
        {
            'key': 'lists_reverse',
            'message0': '%{BKY_LISTS_REVERSE_MESSAGE0}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': 'Array',
                },
            ],
            'output': 'Array',
            'inputsInline': true,
            'style': 'list_blocks',
            'tooltip': '%{BKY_LISTS_REVERSE_TOOLTIP}',
            'helpUrl': '%{BKY_LISTS_REVERSE_HELPURL}',
        },
        {
            'key': 'lists_isEmpty',
            'message0': '%{BKY_LISTS_ISEMPTY_TITLE}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                    'check': ['String', 'Array'],
                },
            ],
            'output': 'Boolean',
            'style': 'list_blocks',
            'tooltip': '%{BKY_LISTS_ISEMPTY_TOOLTIP}',
            'helpUrl': '%{BKY_LISTS_ISEMPTY_HELPURL}',
        },
        {
            'key': 'lists_length',
            'message0': '%{BKY_LISTS_LENGTH_TITLE}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                    'check': 'Array',
                },
            ],
            'output': 'Number',
            'style': 'list_blocks',
        },
        {
            'key': 'lists_pop',
            'message0': '%{lists_pop} %1',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                    'check': 'Array',
                },
            ],
            'output': null,
            "nextStatement": null,
            "previousStatement": null,
            'style': 'list_blocks',
        },
        {
            'key': 'lists_shift',
            'message0': '%{lists_shift} %1',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                    'check': 'Array',
                },
            ],
            'output': null,
            "nextStatement": null,
            "previousStatement": null,
            'style': 'list_blocks',
        },
        {
            'key': 'lists_push',
            'message0': '%{add} %1 %{to} %2 %{lists_push}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                },
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': "Array",
                },
            ],
            'output': 'Number',
            'inputsInline': true,
            "nextStatement": null,
            "previousStatement": null,
            'style': 'list_blocks'
        },
        {
            'key': 'lists_unshift',
            'message0': '%{add} %1 %{to} %2 %{lists_unshift}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                },
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': "Array",
                },
            ],
            'inputsInline': true,
            'output': 'Number',
            "nextStatement": null,
            "previousStatement": null,
            'style': 'list_blocks'
        },
        {
            'key': 'lists_get_item',
            'message0': '%{from} %1 %{get} %{list_the} %2 %{list_th}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': "Array",
                },
                {
                    'type': 'input_value',
                    'name': 'INDEX',
                    'check': "Number",
                },
            ],
            'output': null,
            'style': 'list_blocks',
        },
        {
            'key': 'lists_splice',
            'message0': '%{from} %1 %{lists_splice} %{list_the} %2 %{list_th}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': "Array",
                },
                {
                    'type': 'input_value',
                    'name': 'INDEX',
                    'check': "Number",
                },
            ],
            "nextStatement": null,
            "previousStatement": null,
            'style': 'list_blocks',
        },
        {
            'key': 'list_indexof',
            'message0': '%{from} %1 %{list_indexof} %2 %{list_position}',
            'args0': [
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': "Array",
                },
                {
                    'type': 'input_value',
                    'name': 'VALUE',
                    'check': "Number",
                },
            ],
            'output': 'Number',
            'style': 'list_blocks',
        },
        {
            'key': 'math_on_list',
            'message0': '%1 %2',
            'args0': [
                {
                    'type': 'field_dropdown',
                    'name': 'OP',
                    'options': [
                        ['%{BKY_MATH_ONLIST_OPERATOR_SUM}', 'SUM'],
                        ['%{BKY_MATH_ONLIST_OPERATOR_MIN}', 'MIN'],
                        ['%{BKY_MATH_ONLIST_OPERATOR_MAX}', 'MAX'],
                        ['%{BKY_MATH_ONLIST_OPERATOR_AVERAGE}', 'AVERAGE'],
                        ['%{BKY_MATH_ONLIST_OPERATOR_RANDOM}', 'RANDOM'],
                    ],
                },
                {
                    'type': 'input_value',
                    'name': 'LIST',
                    'check': 'Array',
                },
            ],
            'output': ['Number', 'Array'],
            'style': 'list_blocks',
        },
    ]
    export function init() {
        initGenerator()
        Tanslate.tr(blocks).forEach((item: any) => {
            Blockly.Blocks[item.key] = {
                init: function (this: Blockly.Block) {
                    this.jsonInit(item);
                    if (item.key === 'list_custom') {
                        this.setOnChange((e) => {
                            const ws = this.workspace as WorkspaceSvg;
                            if (
                                !ws.isDragging ||
                                ws.isDragging() ||
                                (e.type !== Blockly.Events.BLOCK_MOVE && e.type !== Blockly.Events.BLOCK_CREATE)
                            ) {
                                return;
                            }
                            if (needAdd(this)) {
                                //this.appendValueInput('value_' + this.getChildren(false).length);
                            }
                        })
                    }
                }
            }
        })
    }

    export function getTools() {
        const colorsBlocks = {
            kind: 'category',
            name: Blockly.Msg['lists'],
            "colour": 260,
            contents: [] as any[]
        }
        blocks.forEach((item: any) => {
            colorsBlocks.contents.push({
                kind: 'block',
                type: item.key
            })
        })

        return colorsBlocks
    }
    const addSate = {
        last: 0
    }
    function needAdd(block: Blockly.Block) {
        const now = Date.now()
        if (addSate.last > 0 && now < addSate.last) {
            return false
        }
        const xy = block.getRelativeToSurfaceXY()
        if (xy.x < 40) {
            return false
        }
        addSate.last = now + 1000
        const ar = block.getChildren(false)
        const size = block.inputList.length
        return ar.length + 1 === size
    }

    function initGenerator() {
        javascriptGenerator.forBlock['lists_repeat'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const ITEM = getValue(block, generator, 'ITEM')
            const NUM = getValue(block, generator, 'NUM')
            if (!ITEM || !NUM) {
                throw new Error(block.id)
            };
            return `Array(${NUM}).fill(${ITEM})`;
        }

        javascriptGenerator.forBlock['list_custom'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const size = block.inputList.length
            const temp: string[] = []
            for (let i = 0; i < size; i++) {
                const value = getValue(block, generator, 'value_' + i)?.trim();
                if (value) {
                    temp.push(value)
                }
            }
            return `[${temp.join(',')}]`;
        }

        javascriptGenerator.forBlock['list_merge'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const list = getValue(block, generator, 'list')?.trim();
            const separator = getValue(block, generator, 'separator')?.trim();
            if (!list || !separator) {
                throw new Error(block.id)
            };
            return `${list}.join(${separator})`;
        }

        javascriptGenerator.forBlock['get_list_length'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const list = getValue(block, generator, 'value')?.trim()
            return `${list}.length`;
        }

        javascriptGenerator.forBlock['lists_reverse'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const ITEM = getValue(block, generator, 'LIST')
            if (!ITEM) {
                throw new Error(block.id)
            };
            return `[${ITEM}.reverse()]`;
        }

        javascriptGenerator.forBlock['lists_isEmpty'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id)
            };
            return `Array.from(${VALUE}).length === 0`;
        }

        javascriptGenerator.forBlock['lists_length'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id)
            };
            return `${VALUE}.length`;
        }

        javascriptGenerator.forBlock['lists_pop'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id)
            };
            if(block.outputConnection?.targetBlock()) {
                return `${VALUE}.pop();`;
            }
            return `${VALUE}.pop();\n`;
        }

        javascriptGenerator.forBlock['lists_shift'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const VALUE = getValue(block, generator, 'VALUE')
            if (!VALUE) {
                throw new Error(block.id)
            };
            if(block.outputConnection?.targetBlock()) {
                return `${VALUE}.shift();`;
            }
            return `${VALUE}.shift();\n`;
        }

        javascriptGenerator.forBlock['lists_push'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const VALUE = getValue(block, generator, 'VALUE')
            if (!LIST || !VALUE) {
                throw new Error(block.id)
            };
            if(block.outputConnection?.targetBlock()) {
                return `${LIST}.push(${VALUE})`;
            }
            return `${LIST}.push(${VALUE});\n`;
        }

        javascriptGenerator.forBlock['lists_unshift'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const VALUE = getValue(block, generator, 'VALUE')
            if (!LIST || !VALUE) {
                throw new Error(block.id)
            };
            if(block.outputConnection?.targetBlock()) {
                return `${LIST}.unshift(${VALUE})`;
            }
            return `${LIST}.unshift(${VALUE});\n`;
        }

        javascriptGenerator.forBlock['list_indexof'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const INDEX = getValue(block, generator, 'INDEX')
            if (!LIST || !INDEX) {
                throw new Error(block.id)
            };
            return `${LIST}.splice(${INDEX}, 1);\n`;
        }

        javascriptGenerator.forBlock['lists_get_item'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const INDEX = getValue(block, generator, 'INDEX')
            if (!LIST || !INDEX) {
                throw new Error(block.id)
            };
            return `${LIST}[${INDEX}]`;
        }

        javascriptGenerator.forBlock['lists_splice'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const VALUE = getValue(block, generator, 'VALUE')
            if (!LIST || !VALUE) {
                throw new Error(block.id)
            };
            return `${LIST}.indexOf(${VALUE})`;
        }

        javascriptGenerator.forBlock['math_on_list'] = function (block: Blockly.Block, generator: JavascriptGenerator) {
            const LIST = getValue(block, generator, 'LIST')
            const OP = getValue(block, generator, 'OP')
            if (!LIST || !OP) {
                throw new Error(block.id)
            };
            if (OP === 'MIN') {
                return `Math.min(${LIST})`;
            } else if (OP === 'MAX') {
                return `Math.max(${LIST})`;
            }else if(OP === 'AVERAGE'){
                return `(${LIST}).reduce((a, b) => a + b, 0) / ${LIST}.length`
            }else if(OP === 'SUM'){
                return `(${LIST}).reduce((a, b) => a + b, 0)`
            }else{
                return `(${LIST}).sort(() => Math.random() - 0.5)`
            }
        }
    }
}
